package org.jetlinks.pro.assets.crud;

import io.swagger.v3.oas.annotations.Parameter;
import lombok.Generated;
import org.hswebframework.ezorm.rdb.mapping.defaults.SaveResult;
import org.hswebframework.web.api.crud.entity.PagerResult;
import org.hswebframework.web.api.crud.entity.QueryParamEntity;
import org.hswebframework.web.authorization.Authentication;
import org.hswebframework.web.crud.web.reactive.ReactiveServiceCrudController;
import org.jetlinks.pro.assets.annotation.AssetsController;
import org.springframework.web.bind.annotation.*;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;

/**
 * 支持数据权限控制的通用增删改查控制器，Controller实现此接口,并注解{@link AssetsController#type()}.
 *
 * @param <E> 实体类型
 * @param <K> 主键类型
 * @author zhouhao
 * @since 1.11
 */
public interface AssetsHolderCrudController<E, K> extends ReactiveServiceCrudController<E, K> {

    @Override
    @AssetsController(ignore = true)
    @Generated
    default E applyAuthentication(E entity, Authentication authentication) {
        return ReactiveServiceCrudController.super.applyAuthentication(entity, authentication);
    }

    @Override
    @AssetsController(ignore = true)
    @Generated
    default E applyCreationEntity(Authentication authentication, E entity) {
        return ReactiveServiceCrudController.super.applyCreationEntity(authentication, entity);
    }

    @Override
    @AssetsController(ignore = true)
    @Generated
    default E applyModifierEntity(Authentication authentication, E entity) {
        return ReactiveServiceCrudController.super.applyModifierEntity(authentication, entity);
    }

    @Override
    @AssetsController(assetObjectIndex = 0, autoBind = true, allowAssetNotExist = true, permission = CrudAssetPermission.permission_save)
    default Mono<SaveResult> save(@RequestBody Flux<E> payload) {
        return ReactiveServiceCrudController.super.save(payload);
    }

    @Override
    default Flux<E> query(@Parameter(hidden = true) QueryParamEntity query) {
        return Flux.defer(() -> ReactiveServiceCrudController.super.query(query));
    }

    @Override
    default Mono<PagerResult<E>> queryPager(@Parameter(hidden = true) QueryParamEntity query) {
        return Mono.defer(() -> ReactiveServiceCrudController.super.queryPager(query));
    }

    @Override
    default Mono<Integer> count(@Parameter(hidden = true) QueryParamEntity query) {
        return Mono.defer(() -> ReactiveServiceCrudController.super.count(query));
    }

    @PutMapping("/{id}")
    @Override
    @AssetsController(permission = CrudAssetPermission.permission_save)
    default Mono<Boolean> update(@PathVariable K id, @RequestBody Mono<E> payload) {
        return ReactiveServiceCrudController.super.update(id, payload);
    }

    @Override
    @AssetsController(assetObjectIndex = 0, validate = false, autoBind = true)
    default Mono<E> add(@RequestBody Mono<E> payload) {
        return ReactiveServiceCrudController.super.add(payload);
    }

    @Override
    @AssetsController(assetObjectIndex = 0, validate = false, autoBind = true)
    default Mono<Integer> add(@RequestBody Flux<E> payload) {
        return ReactiveServiceCrudController.super.add(payload);
    }

    @Override
    @DeleteMapping("/{id:.+}")
    @AssetsController(autoUnbind = true, permission = CrudAssetPermission.permission_delete)
    default Mono<E> delete(@PathVariable K id) {
        return ReactiveServiceCrudController.super.delete(id);
    }

    @Override
    @GetMapping("/{id:.+}")
    @AssetsController(allowAssetNotExist = true)
    default Mono<E> getById(@PathVariable K id) {
        return ReactiveServiceCrudController.super.getById(id);
    }
}
